﻿using Framework.WebApi.Swagger.Filters;

namespace Framework.WebApi.Swagger
{
	public static class SwaggerServiceCollectionExtension
	{
		public static void AddSwagger(this IServiceCollection serviceCollection)
		{
			// 读swagger配置
			var swaggerSetting = App.GetConfig<SwaggerSetting>("SwaggerSetting");

			if (!swaggerSetting.EnableSwagger) return;  // 判断是否启用Swagger

#if !NET5_0
			serviceCollection.AddEndpointsApiExplorer();
#endif
			serviceCollection.AddSwaggerGen(c =>
			{
				c.SwaggerDoc(swaggerSetting.Version, new OpenApiInfo
				{
					Title = swaggerSetting.Title,
					Version = swaggerSetting.Version,
					Description = swaggerSetting.Description,
				});

				// TODO:一定要返回true！
				c.DocInclusionPredicate((docName, description) => true);

				// 本地函数
				static string DefaultSchemaIdSelector(Type modelType)
				{
					var modelName = modelType.Name;

					//Console.WriteLine("old:" + modelName);
					// 处理泛型类型问题
					if (modelType.IsConstructedGenericType)
					{
						var prefix = modelType.GetGenericArguments()
							.Select(genericArg => DefaultSchemaIdSelector(genericArg))
							.Aggregate((previous, current) => previous + current);

						// 通过 _ 拼接多个泛型
						modelName = modelName.Split('`').First() + "_" + prefix;
						//Console.WriteLine("new:" + modelName);
					}

					//// 判断是否自定义了 [SchemaId] 特性，解决模块化多个程序集命名冲突
					//var isCustomize = modelType.IsDefined(typeof(SchemaIdAttribute));
					//if (isCustomize)
					//{
					//	var schemaIdAttribute = modelType.GetCustomAttribute<SchemaIdAttribute>();
					//	if (!schemaIdAttribute.Replace) return schemaIdAttribute.SchemaId + modelName;
					//	else return schemaIdAttribute.SchemaId;
					//}

					return modelName;
				}

				// 调用本地函数,配置 Swagger SchemaIds
				c.CustomSchemaIds(modelType => DefaultSchemaIdSelector(modelType));

				string FileDirectory = AppDomain.CurrentDomain.BaseDirectory;   // 获取基目录

				var assemblyList = AssemblyUtil.GetAssemblyList().Where(w => !w.IsDynamic).ToList();
				foreach (var item in assemblyList)
				{
					// 加载指定swagger文档
					try
					{
						c.IncludeXmlComments(Path.Combine(FileDirectory, item.GetName().Name + ".xml"), true); // 增加swagger文档
						Console.WriteLine("swagger 文档加载:" + item.GetName().Name + ".xml");
					}
					catch (Exception ex)
					{
						Console.WriteLine("swagger 文档加载失败" + ex.Message);
					}
				}

				//参考文章：http://www.zyiz.net/tech/detail-134965.html
				//需要安装包Swashbuckle.AspNetCore.Filters
				// 开启权限小锁 需要在对应的Action上添加[Authorize]才能看到
				//c.OperationFilter<AddResponseHeadersFilter>();
				//c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
				////在header 中添加token，传递到后台
				//c.OperationFilter<SecurityRequirementsOperationFilter>();
				c.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme,
					new OpenApiSecurityScheme
					{
						In = ParameterLocation.Header,
						Description = "请输入Login接口返回的Token，前置Bearer。示例：Bearer {Token}",
						Name = "Authorization",//jwt默认的参数名称,
						Type = SecuritySchemeType.ApiKey, //指定ApiKey
						BearerFormat = "JWT",//标识承载令牌的格式 该信息主要是出于文档目的
						Scheme = JwtBearerDefaults.AuthenticationScheme//授权中要使用的HTTP授权方案的名称
					});
				c.AddSecurityRequirement(new OpenApiSecurityRequirement
				{
					{
						new OpenApiSecurityScheme
						{
							Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
						},
						new List<string>()
					}
				});

				// 修复 editor.swagger.io 生成不能正常处理 C# object 类型问题
				c.SchemaFilter<AnySchemaFilter>();

				c.OperationFilter<AuthenticationOperationFilter>();
			});


			if (!App.GetConfig<Boolean>("EnableMiniProfiler")) return;	// 判断是否启用MiniProfiler

			// 配置MiniProfiler服务
			serviceCollection.AddMiniProfiler(options =>
			{
				//这里是配置了MiniProfiler的路由基础路径，默认的路径是/mini-profiler-resources
				//按照当前配置，你可以使用"/profiler/results"来访问分析报告
				options.RouteBasePath = "/profiler";
			});
		}
	}
}
